package memgraph

import "trigger.googlecode.com/hg/lib/rdf"

type sink struct {
    prefixes map[string]string
    G rdf.Graph
}

type MemGraph struct {
    bySubject *mapThing
    byPredicate *mapThing
    byObject *mapThing
}

type mapThing struct {
    field func(rdf.Triple) rdf.Node
    lookup map[rdf.Node][]rdf.Triple
}

func (m *mapThing) Add(t rdf.Triple) bool {
    key := m.field(t)
    slice, present := m.lookup[key]
    if present {
        for _, x := range slice {
            if t == x { return false }
        }
        m.lookup[key] = append(slice, t)
        return true
    } else {
        m.lookup[key] = []rdf.Triple{t}
        return true
    }
    return true
}

func (m *mapThing) Contains(t rdf.Triple) bool {
    key := m.field(t)
    slice, present := m.lookup[key]
    if present {
        for _, x := range slice {
            if x == t { return true }
        }
    }
    return false
}

func (m *mapThing) Remove(t rdf.Triple) bool {
    key := m.field(t)
    slice, present := m.lookup[key]
    if present {
        for i, x := range slice {
            if t == x {
                if i == len(slice) - 1 {
                    m.lookup[key] = slice[:i]
                } else {
                    slice[i] = slice[len(slice) - 1]
                    m.lookup[key] = slice[:len(slice)]
                }
                return true
            }
        }
        return false
    }
    return false
}

func NewMapThing(field func (rdf.Triple) rdf.Node) *mapThing {
    return &mapThing{field, map[rdf.Node][]rdf.Triple{}}
}

func (m *MemGraph) Add(t rdf.Triple) bool {
    if m.bySubject.Add(t) {
        m.byPredicate.Add(t)
        m.byObject.Add(t)
        return true
    }
    return false
}

func (m *MemGraph) Remove(t rdf.Triple) bool {
    if m.bySubject.Remove(t) {
        m.byPredicate.Remove(t)
        m.byObject.Remove(t)
        return true
    }
    return false
}

func (m *MemGraph) Contains(t rdf.Triple) bool {
    return m.bySubject.Contains(t)
}

func (m *MemGraph) FindAll(t rdf.Triple, f func (rdf.Triple) bool) bool {
    return false
}

func NewMemGraph() *MemGraph {
    return &MemGraph{NewMapThing(rdf.Triple.S), NewMapThing(rdf.Triple.P), NewMapThing(rdf.Triple.O)}
}

